from rest_framework import serializers # 序列化
from django.contrib.auth.models import User # 用户模型
from rest_framework_simplejwt.serializers import TokenObtainSlidingSerializer # 导入原来的TokenObtainSlidingView的视图类的序列化类
from django_redis import get_redis_connection # 导入连接redis数据库的方法
from wen.redisconfile import LOGIN_KEY_TEMPLATE # 导入redis键名的前半部分
from django.contrib.auth.models import User  # 导入用户模型
from .models import UserParticulars # 用户详情模型
from rest_framework.routers import Response # 返回



# 用户详情序列化
class UserParticularsSerializer(serializers.ModelSerializer):
    # 源类固定的
    class Meta:
        model = UserParticulars # 指定用户的详情模型
        fields = '__all__' # 展示所有字段


        extra_kwargs = {
            'user':{'write_only':True},# 外键字段 只写入不在前端展示
            'avatar':{'read_only':True}, # 头像 单独写接口,不想在详情中修改


        }



# 用户的个人信息
class UserSerializer(serializers.ModelSerializer):  # 把用户模型给序列化
    # 注意:变量名要是用户详情的源模型的小写名  正向操作模型
    userparticulars = UserParticularsSerializer(read_only=True,required=False)  # 定义:用户详情字段
    # 源类固定的
    class Meta:
        model = User  # 用户模型
        exclude = ['password', 'last_name', 'user_permissions']  # 排除密码与姓氏字段,user_permissions:用户权限 其他字段的都展示
        # 修改字段
        extra_kwargs = {
            'last_login': {'read_only': True},  # 上次登录修改为,只看不修改
            'is_superuser': {'read_only': True},  # 权限字段,只看不修改
            'is_staff': {'read_only': True},  # 工作人员字段,只看不修改
            'is_active': {'read_only': True},  # 有效用户字段,只看不修改
            'date_joined': {'read_only': True},  # 加入日期,只看不修改
            'groups': {'read_only': True},  # 组,只看不修改

        }


# 用户的密码序列化器
class UserPasswordSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=60,label='旧密码')
    new_password = serializers.CharField(max_length=60,label='新密码')
    repeat_password = serializers.CharField(max_length=60,label='确认密码')


    # 自定义校验方法: 全字段校验
    def validate(self, attrs):
        if attrs['new_password'] != attrs['repeat_password']:
            raise serializers.ValidationError('两次密码不一致')  # 抛出错误
        return attrs













# simple让返回的令牌携带用户信息
class TokenSerializer(TokenObtainSlidingSerializer): # 继承原来的父类

    # 重写原来的校验方法
    def validate(self, attrs):
        data = super().validate(attrs)
        data['user_id'] = self.user.id # 获取id赋值给data
        data['username'] = self.user.username # 获取用户名赋值给data

        # 图片验证码的校验
        # 1. 获取前端的uuid与验证码
        uuid = self.initial_data.get('uuid')  # 获取uuid的后部分键名
        value = self.initial_data.get('verify') # 获取用户输入进行的验证码


        # 2. 获取后端数据库的uuid键名与验证码
        # 连接redis数据库
        cont_redis = get_redis_connection(alias='verify_codes')  # alias 指定setting配置文件使用哪个库
        # 获取后端的验证码
        value_redis = cont_redis.get(LOGIN_KEY_TEMPLATE % uuid)  # 传入键名获取之后获取值



        if not value or not uuid:  # 查看是否存在验证码
            return {'msg': '请输入验证码'}

        cont_redis.delete(LOGIN_KEY_TEMPLATE % uuid)  # 及时的删除释放空间

            # 验证码是否有效
        if not value_redis:
            return {'msg': "验证码过期"}


        # 比较前后端的值
        if value.lower() != value_redis.lower():
            return {'msg':'验证码错误'}


        return data




# 注册的用户
class RegisUserSerializer(serializers.ModelSerializer):
    # 源类
    class Meta:
        model = User # 用户模型
        # 展示哪些字段
        fields = ['username','first_name','email'] # 第一个:账号名,第二个:姓名,第三个:邮箱

        # 给已有的字段修改参数
        extra_kwargs = {
            'first_name':{
                'required':True  # 修改为该字段是必填,不能为空,原本可以为空
            },
            'email':{
                'required':True # 修改为该字段是必填,不能为空,原本是可以为空的
            }
        }
